From b856f05d5fb17091c87609e97d9012deb09bcc80 Mon Sep 17 00:00:00 2001 From: robertl Date: Wed, 14 Aug 2002 16:20:51 +0000 Subject: [PATCH] Initial version of CetusGPS support. --- ChangeLog | 2 + cetus.c | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 ChangeLog create mode 100644 cetus.c diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 000000000..e4e085b63 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,2 @@ +NEW: blah blah +NEW: Add Cetus support. Thanx to Ron Parker and Kjeld Jensen. diff --git a/cetus.c b/cetus.c new file mode 100644 index 000000000..3a33cce77 --- /dev/null +++ b/cetus.c @@ -0,0 +1,281 @@ +/* + Read and write Cetus files. + + Copyright (C) 2002 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#include "coldsync/palm.h" +#include "coldsync/pdb.h" + +typedef struct { + unsigned char data[4]; +} pdb_32; + +typedef struct { + unsigned char data[2]; +} pdb_16; + + +struct record { + char type; + char ID[16]; /* Zero-terminated string. */ + char name[61]; /* zero-terminated */ + pdb_32 latitude; /* Big endian, degrees*1e7, s=negative */ + pdb_32 longitude; /* same as lat; w=negative */ + unsigned char hour; /* sample time, UTC */ + unsigned char min; + unsigned char sec; + unsigned char year; /* 2002 = 02 */ + unsigned char mon; + unsigned char day; + pdb_32 elevation; /* Big endian, meters*100. blank=-1e8 */ + char fix_quality; /* 3 = 3d fix, 0=no fix */ + char sats_tracked; /* ff if averaged or unknown */ + pdb_16 hdop; + pdb_16 dgpstime; + pdb_32 dgpsstn; + pdb_32 avgtime; + pdb_32 avgite; + pdb_16 icon; + char category; + char flagged; + char readonly; +}; + +static FILE *file_in; +static FILE *file_out; +static const char *out_fname; +struct pdb *opdb; +struct pdb_record *opdb_rec; + +static void +rd_init(const char *fname) +{ + file_in = fopen(fname, "r"); + if (file_in == NULL) { + fatal("CETUS: Cannot open %s for reading\n", fname); + } +} + +static void +rd_deinit(void) +{ + fclose(file_in); +} + +static void +wr_init(const char *fname) +{ + file_out = fopen(fname, "w"); + out_fname = fname; + if (file_out == NULL) { + fatal("CETUS: Cannot open %s for writing\n", fname); + } +} + +static void +wr_deinit(void) +{ + fclose(file_out); +} + +/* + * Read 4 bytes in big-endian. Return as "int" in native endianness. + */ +int +read4(pdb_32 *p) +{ + char *i = (char *) p; + return i[0] << 24 | i[1] << 16 | i[2] << 8 | i[3]; +} + +void +write4(pdb_32 *pp, unsigned i) +{ + char *p = (char *)pp; + + p[0] = (i >> 24) & 0xff; + p[1] = (i >> 16) & 0xff; + p[2] = (i >> 8) & 0xff; + p[3] = i & 0xff; +} + +static void +data_read(void) +{ + struct record *rec; + struct pdb *pdb; + struct pdb_record *pdb_rec; + + if (NULL == (pdb = pdb_Read(fileno(file_in)))) { + fatal("pdb_Read failed"); + } + + for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) { + waypoint *wpt_tmp; + + wpt_tmp = calloc(sizeof(*wpt_tmp),1); + if (wpt_tmp == NULL) { + fatal("CETUS: cannot allocate memory\n"); + } + + rec = (struct record *) pdb_rec->data; + wpt_tmp->shortname = strdup(rec->ID); + wpt_tmp->description = strdup(rec->name); + wpt_tmp->position.altitude.altitude_meters = read4(&rec->elevation) / 100.0; + + wpt_tmp->position.longitude.degrees = read4(&rec->longitude) / 10000000.0; + wpt_tmp->position.latitude.degrees = read4(&rec->latitude) / 10000000.0; + if (rec->year != 0xff) { + struct tm tm = {0}; + time_t tval; + + tm.tm_min = rec->min; + tm.tm_hour = rec->hour; + tm.tm_mday = rec->day; + tm.tm_mon = rec->mon - 1; + tm.tm_year = rec->year + 100; + + wpt_tmp->creation_time = mktime(&tm); + + } + waypt_add(wpt_tmp); + + } + free_pdb(pdb); +} + + +static void +cetus_writewpt(waypoint *wpt) +{ + struct record *rec; + static int ct; + struct tm *tm; + + rec = calloc(sizeof(*rec),1); + + strncpy(rec->ID, wpt->shortname, sizeof(rec->ID)); + rec->ID[sizeof(rec->ID)-1] = 0; + strncpy(rec->name, wpt->description, sizeof(rec->name)); + rec->name[sizeof(rec->name)-1] = 0; + + if (wpt->creation_time) { + tm = gmtime(&wpt->creation_time); + rec->min = tm->tm_min; + rec->hour = tm->tm_hour; + rec->sec = tm->tm_sec; + rec->day = tm->tm_mday; + rec->mon = tm->tm_mon + 1; + rec->year = tm->tm_year - 100; + } else { + rec->min = 0xff; + rec->hour = 0xff; + rec->sec = 0xff; + rec->day = 0xff; + rec->mon = 0xff; + rec->year = 0xff; + } + + write4(&rec->longitude, wpt->position.longitude.degrees * 10000000.0); + write4(&rec->latitude, wpt->position.latitude.degrees * 10000000.0); + write4(&rec->elevation, wpt->position.altitude.altitude_meters * 100.0); + + opdb_rec = new_Record (0, 0, ct++, sizeof(*rec), (const ubyte *)rec); + + if (opdb_rec == NULL) { + fatal("libpdb couldn't create record"); + } + + if (pdb_AppendRecord(opdb, opdb_rec)) { + fatal("libpdb couldn't append record"); + } +} + +struct hdr{ + char *wpt_name; + waypoint *wpt; +}; + +static +int +compare(const void *a, const void *b) +{ + const struct hdr *wa = a; + const struct hdr *wb = b; + + return strcmp(wa->wpt->shortname, wb->wpt->shortname); +} + +static void +data_write(void) +{ + int i, ct = waypt_count(); + struct hdr *htable, *bh; + queue *elem, *tmp; + extern queue waypt_head; + waypoint *waypointp; + + if (NULL == (opdb = new_pdb())) { + fatal ("new_pdb failed\n"); + } + + strncpy(opdb->name, out_fname, PDB_DBNAMELEN); + opdb->name[PDB_DBNAMELEN-1] = 0; + opdb->attributes = PDB_ATTR_BACKUP; + opdb->ctime = opdb->mtime = time(NULL) + 2082844800U; + opdb->type = 0x43577074; /* CWpt */ + opdb->creator = 0x63475053; /* cGPS */ + opdb->version = 0; + + /* + * All this is to sort by waypoint names before going to Cetus. + * Turns out plain old strcmp will do the trick... + */ + + htable = malloc(ct * sizeof(*htable)); + bh = htable; + if (!htable) { + fatal ("Cannot get array for sorting waypoints."); + } + QUEUE_FOR_EACH(&waypt_head, elem, tmp) { + waypointp = (waypoint *) elem; + bh->wpt = waypointp; + bh->wpt_name = waypointp->shortname; + bh ++; + } + qsort(htable, ct, sizeof(*bh), compare); + + for (i=0;i